package services;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.ParseException;
import java.util.Date;

import models.Author;
import models.Book;
import models.Cover;
import models.ReadingSheet;
import models.User;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.apache.commons.lang.time.DateUtils;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.usermodel.Picture;

import play.Logger;
import play.Play;
import play.db.jpa.Transactional;
import services.dto.SheetFileInfoDTO;
import services.exception.InvalidDocumentException;
import utils.AuthorTypeEnum;
import utils.Constants;

public class FileImportationImpl implements FileImportation {

	
	@Override
	@Transactional //TODO verif que ça marche
	public Long importSheet(final User user, final File sheetFile) throws IOException, InvalidDocumentException {
		
		InputStream is = new FileInputStream(sheetFile);
		HWPFDocument wordDoc; 
		try {
			wordDoc = new HWPFDocument(is);
		} catch (IOException e) {
			throw new InvalidDocumentException(InvalidDocumentException.MSG_INVALID_FORMAT, e);
		}
		String[] paragraphTab = StringUtils.chomp(wordDoc.getDocumentText()).split(FileImportationCst.STR_BRR_2);
		
		SheetFileInfoDTO infoDTO = new SheetFileInfoDTO();
		
		String[] decoup;
		for (String t : paragraphTab) {
			if (t.contains(FileImportationCst.STR_TAB_2)) {
				// 2 info on the same line
				decoup = t.split(FileImportationCst.STR_TAB_2);
				parseParagraphAndFillDto(decoup[0], infoDTO);
				parseParagraphAndFillDto(decoup[decoup.length-1], infoDTO);
			} else {
				parseParagraphAndFillDto(t, infoDTO);
			}
		}
		
		Author author = Author.find("byNameAndType", infoDTO.getAuthorName(), AuthorTypeEnum.WRITER.getValue()).first();
		if (author == null) {
			author = new Author(infoDTO.getAuthorName(), infoDTO.getAuthorFirstname(), AuthorTypeEnum.WRITER.getValue());
			author.create();
		}
		
		Book book = Book.find("byTitleAndAuthor", infoDTO.getTitle(), author).first();
		if (book == null) {
			book = new Book(infoDTO.getTitle(), author);
			book.translation = infoDTO.getTranslation();
			book.category = infoDTO.getCategory();
			book.nbpage = infoDTO.getNbPages();
			//book.year = infoDTO.getPublicationDate();
			book.create();
		}
		
		// create the reading sheet
		ReadingSheet sheet = new ReadingSheet(user, book, infoDTO.getGrade(), infoDTO.getReadingDate(), infoDTO.getOrigin(), 
				infoDTO.getComment(), infoDTO.getResume(), infoDTO.getBeginning(), infoDTO.getPiece(), infoDTO.getPiecePage(), 0);
		sheet.save();
		
		// cover
		int i = 1;
		for (Picture coverPicture : wordDoc.getPicturesTable().getAllPictures()) {
			String fileName = "import_" + coverPicture.suggestFullFileName();
			File to = Play.getFile("public/images/cover/" + fileName);
			OutputStream out = new FileOutputStream(to);
			coverPicture.writeImageContent(out);
			
			// create cover
        	Cover coverModel = new Cover(book, i, fileName);
        	coverModel.create(); 
        	i++;
		}
		
		return sheet.id;
	}
	
	
	
	private static void parseParagraphAndFillDto(final String textParagraph, final SheetFileInfoDTO infoDTO) {
		
		String text = StringUtils.removeStart(textParagraph, FileImportationCst.STR_BRR_1);
	
		if (text.contains(FileImportationCst.KEY_TITLE)) {
			infoDTO.setTitle(StringUtils.normalizeSpace(StringUtils.remove(text, FileImportationCst.KEY_TITLE)));
		} else if (text.contains(FileImportationCst.KEY_AUTHOR)) {
			String author = StringUtils.reverseDelimited(StringUtils.remove(text, FileImportationCst.KEY_AUTHOR), ' ');
			infoDTO.setAuthorFirstname(StringUtils.substringBeforeLast(author, " "));
			infoDTO.setAuthorName(StringUtils.substringAfterLast(author, " "));
		} else if (text.contains(FileImportationCst.KEY_TRANSLATION)) {
			infoDTO.setTranslation(StringUtils.normalizeSpace(StringUtils.remove(text, FileImportationCst.KEY_TRANSLATION)));
		} else if (text.contains(FileImportationCst.KEY_CATEGORY)) {
			infoDTO.setCategory(StringUtils.normalizeSpace(StringUtils.remove(text, FileImportationCst.KEY_CATEGORY)));
		} else if (text.contains(FileImportationCst.KEY_EDITOR)) {
			infoDTO.setEditor(StringUtils.normalizeSpace(StringUtils.remove(text, FileImportationCst.KEY_EDITOR)));
		} else if (text.contains(FileImportationCst.KEY_PUB_DATE)) {
			try {
				Date date = DateUtils.parseDate(StringUtils.normalizeSpace(StringUtils.remove(text, FileImportationCst.KEY_PUB_DATE)), Constants.DATE_PATTERN_ARRAY);
				infoDTO.setPublicationDate(date);
			} catch (ParseException e) {
				Logger.warn(e, "impossible de convertir la date %s", text);
			}
		} else if (text.contains(FileImportationCst.KEY_PAGE_NB)) {
			int nb = NumberUtils.toInt(StringUtils.normalizeSpace(StringUtils.remove(text, FileImportationCst.KEY_PAGE_NB)));
			infoDTO.setNbPages(nb);
		} else if (text.contains(FileImportationCst.KEY_ORIGIN)) {
			infoDTO.setOrigin(StringUtils.normalizeSpace(StringUtils.remove(text, FileImportationCst.KEY_ORIGIN)));
		} else if (text.contains(FileImportationCst.KEY_BEGINNING)) {
			String richText = StringUtils.remove(text, FileImportationCst.KEY_BEGINNING);
			infoDTO.setBeginning(StringUtils.replace(richText, FileImportationCst.STR_BRR_1, FileImportationCst.HTML_BR_TAG));
		} else if (text.contains(FileImportationCst.KEY_RESUME)) {
			String richText = StringUtils.remove(text, FileImportationCst.KEY_RESUME);
			infoDTO.setResume(StringUtils.replace(richText, FileImportationCst.STR_BRR_1, FileImportationCst.HTML_BR_TAG));
		} else if (text.contains(FileImportationCst.KEY_COMMENT)) {
			String richText = StringUtils.remove(text, FileImportationCst.KEY_COMMENT);
			infoDTO.setComment(StringUtils.replace(richText, FileImportationCst.STR_BRR_1, FileImportationCst.HTML_BR_TAG));
		} else if (text.contains(FileImportationCst.KEY_PIECE)) {
			infoDTO.setPiecePage(StringUtils.normalizeSpace(StringUtils.remove(StringUtils.substringBefore(text, FileImportationCst.KEY_PIECE_2), FileImportationCst.KEY_PIECE)));
			infoDTO.setPiece(StringUtils.replace(StringUtils.remove(StringUtils.substringAfter(text, FileImportationCst.KEY_PIECE_2), FileImportationCst.KEY_PIECE), FileImportationCst.STR_BRR_1, FileImportationCst.HTML_BR_TAG));
		} else if (text.contains(FileImportationCst.KEY_GRADE)) {
			int nb = NumberUtils.toInt(StringUtils.trim(StringUtils.remove(text, FileImportationCst.KEY_GRADE)));
			infoDTO.setGrade(nb);
		} else if (text.contains(FileImportationCst.KEY_READ_DATE)) {
			try {
				Date date = DateUtils.parseDate(StringUtils.trim(text), Constants.DATE_PATTERN_ARRAY);
				infoDTO.setReadingDate(date);
			} catch (ParseException e) {
				Logger.warn(e, "impossible de convertir la date %s", text);
			}
		} 
	}

}
